
#include "commmsg.h"
#include "commerrno.h"
#include "../cmd/dataprepare.h"
#include "cmddrug.h"
#include "../mainctrl.h"
#include "../storage/CStorageMgr.h"
#include "../instance/CInstanceMgr.h"

CT_REGISTER_ASYNCCMD(ID_MAIN_ROLE_DURG_INFO , CCmdRoleDrugInfo);
int CCmdRoleDrugInfo::Do(void* pData)
{
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_ROLE_DURG_INFO ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_ROLE_DURG_INFO,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    //检查登录
    iRet = pstMainCtrl->CheckLogin(stReq.gid(), stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdRoleDrugInfo::LogicDo(int iRet)
{
    if (iRet)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, stReq.gid());
    PREPARE_PLAYER_DETAIL_INFO(this, stReq.gid());
    PREPARE_PLAYER_ONLINE_DATA(this, stReq.gid());

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        CT_ERROR(("get user player base info error, uid = %u", stReq.gid()));
        return AnsClients(RET_SYSTEM_FAIL);
    }
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    //检查系统是否开启
    short usRoleLevel = 0;
    pstMainCtrl->m_stRoleMgr.GetRoleLevel(stReq.gid(), usRoleLevel);
    if (!pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_14, stPlayerBaseInfo, stPlayerOnlineData))
    {
        return AnsClients(ERROR_SYS_NOT_OPEN);
    }

    unsigned short usRoldId = (unsigned short)(stReq.role_id() & 0x7FFF);
    iRet = pstMainCtrl->m_stDrugMgr.GetRoleDrugInfo(stPlayerDetailInfo, usRoldId, stAns);
    return AnsClients(iRet);
}

int CCmdRoleDrugInfo::AnsClients(int iRet)
{
    pstMainCtrl->m_stEncodeBuf.Clear();

    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    stAns.set_gid(stReq.gid());
    stAns.set_roleid(stReq.role_id());
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);

    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf, true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}


CT_REGISTER_ASYNCCMD(ID_MAIN_MAKE_DRUG , CCmdMakeDrug);
int CCmdMakeDrug::Do(void* pData)
{
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_MAKE_DRUG ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_MAKE_DRUG,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    //检查登录
    iRet = pstMainCtrl->CheckLogin(stReq.gid(), stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdMakeDrug::LogicDo(int iRet)
{
    if (iRet)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, stReq.gid());
    PREPARE_PLAYER_DETAIL_INFO(this, stReq.gid());
    PREPARE_PLAYER_ONLINE_DATA(this, stReq.gid());
    PREPARE_PLAYER_DETAIL_EX1_INFO(this, stReq.gid());

    int iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(stReq.gid());
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    iRet = PreCheck(stPlayerBaseInfo, stPlayerDetailInfo, stPlayerOnlineData);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    unsigned uiNotifyType = 0;
    bool bNeedSaveBaseInfo = false;
    bool bNeedSaveDetailInfo = false;
    switch (stReq.opt())
    {
    case MAKE_DRUG_PREVEIW:
        break;

    case MAKE_DRUG_SYNTHETIZE:
        {
            iRet = pstMainCtrl->m_stDrugMgr.SynthetizeDrug(stPlayerBaseInfo, stPlayerDetailInfo, stPlayerOnlineData, stReq, stAns);
            if (RET_OK == iRet)
            {
                bNeedSaveBaseInfo = true;
                bNeedSaveDetailInfo = true;
                uiNotifyType = NOTIFY_BAG_INFO | NOTIFY_USER_MONEY;
            }
        }
        break;

    case MAKE_DRUG_PURIFY:
        {
#if 0
            iRet = pstMainCtrl->m_stDrugMgr.PurifyDrug(stPlayerBaseInfo, stPlayerDetailInfo, stPlayerOnlineData, stReq, stAns);
            if (RET_OK == iRet)
            {
                bNeedSaveBaseInfo = true;
                bNeedSaveDetailInfo = true;
                uiNotifyType = NOTIFY_BAG_INFO | NOTIFY_USER_MONEY;
            }
#endif
            //TASK #191::关闭魔药
            iRet = ERROR_SYS_NOT_OPEN;
        }
        break;
    }

    if (iRet)
    {
        return AnsClients(iRet);
    }

    CVarObjectKey stKey;
    stKey.m_u64ID = stPlayerBaseInfo._uiGID;
    if (bNeedSaveBaseInfo)
    {
        stKey.m_chDataType = DT_PLAYER_BASE_INFO;
        pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);
    }

    if (bNeedSaveDetailInfo)
    {
        stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
        pstMainCtrl->m_stStorageMgr.GetData(stPlayerOnlineData._stUserStorage, stPlayerDetailInfo._stUserStorage);
        pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);
    }

    pstMainCtrl->m_stNotifyMgr.Notify(stPlayerBaseInfo._uiGID, uiNotifyType);
    pstMainCtrl->m_stDrugMgr.GetDrugMakeInfo(stPlayerDetailInfo, stPlayerOnlineData,
                                             stReq.role_id(), stReq.drug_id(), *(stAns.mutable_info()));
    return AnsClients(RET_OK);
}

int CCmdMakeDrug::AnsClients(int iRet)
{
    pstMainCtrl->m_stEncodeBuf.Clear();

    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    stAns.set_gid(stReq.gid());
    stAns.set_opt(stReq.opt());
    stAns.set_role_id(stReq.role_id());
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);

    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf,true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

int CCmdMakeDrug::PreCheck (CPlayerBaseInfo & stPlayerBaseInfo, CPlayerDetailInfo& stPlayerDetailInfo, CPlayerOnlineData & stPlayerOnlineData)
{
    int iRet = RET_OK;
    int iOpt = stReq.opt();

    iRet = pstMainCtrl->m_stDrugMgr.CheckRoleId(stPlayerDetailInfo, stReq.role_id());
    CHECK_RETURN(iRet);

    if(!pstMainCtrl->m_stDrugMgr.IsValidDrug(stReq.drug_id()))
    {
        return EROOR_DRUG_NOT_EXIST;
    }

    //检查系统是否开启
    switch (iOpt)
    {
    case MAKE_DRUG_PREVEIW:
        {

        }
        break;

    case MAKE_DRUG_SYNTHETIZE:
        if (!pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_14, stPlayerBaseInfo, stPlayerOnlineData))
        {
            iRet = ERROR_SYS_NOT_OPEN;
        }
        break;

    case MAKE_DRUG_PURIFY:
        if ((MAKE_DRUG_GOLD == stReq.method())
            && (!pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_22, stPlayerBaseInfo, stPlayerOnlineData)))
        {
            iRet = ERROR_SYS_NOT_OPEN;
        }
        break;

    default:
        iRet = ERROR_DRUG_UNSUPPORT_OPER;
    }

    return iRet;
}

CT_REGISTER_ASYNCCMD(ID_MAIN_INHERIT_DRUG , CCmdInheritDrug);
int CCmdInheritDrug::Do(void* pData)
{
    CCmdPBDoParam* pstParam = (CCmdPBDoParam*) pData;
    pstMainCtrl = (CMainCtrl*) pstParam->m_pMain;

    if (pstParam->m_pstMsgHead->msgid() != ID_MAIN_INHERIT_DRUG ||
        pstParam->m_pstMsgHead->msgtype() != CSMsgDef::EMT_REQUEST)
    {
        CT_ERROR(("Cmd Stat Err Cmd=%d CmdID=%d Tpye=%d",
            ID_MAIN_INHERIT_DRUG,
            pstParam->m_pstMsgHead->msgid(),
            pstParam->m_pstMsgHead->msgtype()));
        return Done(RET_SYS_ERROR);
    }

    stMsgHead = *(pstParam->m_pstMsgHead);
    stEnpHead = *(pstParam->m_pstEnpHead);
    int iRet = pstMainCtrl->DecodePBMsg(stReq, pstParam);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    _uiGid = (unsigned int)stReq.gid();

    //检查登录
    iRet = pstMainCtrl->CheckLogin(_uiGid, stEnpHead);
    if (iRet != RET_OK)
    {
        return AnsClients(iRet);
    }

    LogicDo(RET_OK);
    return RET_OK;
}

int CCmdInheritDrug::LogicDo(int iRet)
{
    if (iRet)
    {
        return AnsClients(iRet);
    }

    PREPARE_PLAYER_BASE_INFO(this, _uiGid);
    ASSERT_PLAYER_PREPARED(_uiGid);

    PREPARE_PLAYER_DETAIL_INFO(this, _uiGid);
    ASSERT_PLAYER_DETAIL_PREPARED(_uiGid);
    PREPARE_PLAYER_ONLINE_DATA(this, _uiGid);

    int iIndex;
    iIndex = pstMainCtrl->m_stPlayerBaseInfoHash.HashFind(_uiGid);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerBaseInfo& stPlayerBaseInfo = pstMainCtrl->m_stPlayerBaseInfoHash[iIndex];

    if (stPlayerBaseInfo._ucIsInited != 1)
    {
        return AnsClients(ERROR_NOT_INITED);
    }

    iIndex = pstMainCtrl->m_stPlayerDetailInfoHash.HashFind(_uiGid);
    if (iIndex < 0)
    {
        return AnsClients(RET_NO_USER);
    }
    CPlayerDetailInfo& stPlayerDetailInfo = pstMainCtrl->m_stPlayerDetailInfoHash[iIndex];

    iIndex = pstMainCtrl->m_stPlayerOnlineDataHash.HashFind(_uiGid);
    if (iIndex < 0)
    {
        CT_ERROR(("no user %u", _uiGid));
        return AnsClients(RET_NO_USER);
    }
    CPlayerOnlineData& stPlayerOnlineData = pstMainCtrl->m_stPlayerOnlineDataHash[iIndex];

    iRet = PreCheck(stPlayerBaseInfo, stPlayerDetailInfo, stPlayerOnlineData);
    if (iRet)
    {
        return AnsClients(iRet);
    }

    unsigned short usSrcRoleId = (unsigned short)(stReq.src_role_id() & 0x7FFF);
    unsigned short usDstRoleId = (unsigned short)(stReq.dst_role_id() & 0x7FFF);
    CDrugData  & stSrcDrug = pstMainCtrl->m_stDrugMgr.GetUserDrug (stPlayerDetailInfo, usSrcRoleId);
    CDrugData  & stDstDrug = pstMainCtrl->m_stDrugMgr.GetUserDrug (stPlayerDetailInfo, usDstRoleId);

    int iOpt = stReq.opt();
    bool bNeedSaveBaseInfo = false;
    bool bNeedSaveDetailInfo = false;
    unsigned uiNotifyType = 0;

    switch (iOpt)
    {
    case OPT_PREVIEW_INHERIT:
        {
            pstMainCtrl->m_stDrugMgr.GetDrugInheritInfo(stPlayerDetailInfo, stReq, stAns);
        }
        break;

    case OPT_INHERIT_GOLD:
        {
            iRet = pstMainCtrl->m_stDrugMgr.InheritDrug(stSrcDrug, stDstDrug, true);
            if (RET_OK == iRet)
            {
                pstMainCtrl->m_stItemMgr.SubGold(stPlayerBaseInfo, OSS_MONEY_MODULE_27, _iNeedGold);
                bNeedSaveBaseInfo = true;
                bNeedSaveDetailInfo = true;
                uiNotifyType = NOTIFY_USER_MONEY;
            }
        }
        break;

    case OPT_INHERIT_SILVER:
        {
            iRet = pstMainCtrl->m_stDrugMgr.InheritDrug(stSrcDrug, stDstDrug, false);
            if (RET_OK == iRet)
            {
                CMainCtrl::m_pstMain->m_stItemMgr.SubSilver(stPlayerBaseInfo, _iNeedSilver, 0);
                bNeedSaveBaseInfo = true;
                bNeedSaveDetailInfo = true;
                uiNotifyType = NOTIFY_USER_MONEY;
            }
        }
        break;

    default:
        iRet = ERROR_DRUG_UNSUPPORT_OPER;
    }

    if (iRet)
    {
        return AnsClients(iRet);
    }

    CVarObjectKey stKey;
    stKey.m_u64ID = stPlayerBaseInfo._uiGID;
    if (bNeedSaveBaseInfo)
    {
        stKey.m_chDataType = DT_PLAYER_BASE_INFO;
        pstMainCtrl->UpdateData(stKey, stPlayerBaseInfo, VOP_UPDATE);
    }

    if (bNeedSaveDetailInfo)
    {
        pstMainCtrl->m_stDrugMgr.CalcRoleAttr(stPlayerBaseInfo, stPlayerDetailInfo, stPlayerOnlineData, usSrcRoleId);
        pstMainCtrl->m_stDrugMgr.CalcRoleAttr(stPlayerBaseInfo, stPlayerDetailInfo, stPlayerOnlineData, usDstRoleId);
        stKey.m_chDataType = DT_PLAYER_DETAIL_INFO;
        pstMainCtrl->UpdateData(stKey, stPlayerDetailInfo, VOP_UPDATE);
    }

    CT_BILL(("%d|%d|%u|%d|%d|%d", CMainCtrl::m_pstMain->m_iNow, OSS_MODULE_DRUG_INHERIT, _uiGid, usSrcRoleId, usDstRoleId, iOpt));
    pstMainCtrl->m_stNotifyMgr.Notify(stPlayerBaseInfo._uiGID, uiNotifyType);
    return AnsClients(RET_OK);
}

int CCmdInheritDrug::AnsClients(int iRet)
{
    pstMainCtrl->m_stEncodeBuf.Clear();

    stMsgHead.set_msgret(iRet);
    stMsgHead.set_msgtype(CSMsgDef::EMT_ANSWER);

    if (iRet != RET_OK)
    {
        pstMainCtrl->ReturnMsgHead(stMsgHead, stEnpHead);
        return Done(iRet);
    }

    stAns.set_gid(stReq.gid());
    stAns.set_opt(stReq.opt());
    stAns.set_dst_role_id(stReq.dst_role_id());
    pstMainCtrl->EncodePBMsg(stMsgHead, pstMainCtrl->m_stEncodeBuf);
    pstMainCtrl->EncodePBMsg(stAns, pstMainCtrl->m_stEncodeBuf);

    if (pstMainCtrl->AnswerToClient(stEnpHead, pstMainCtrl->m_stEncodeBuf,true))
    {
        CT_WARNING((""));
        return Done(RET_SYS_ERROR);
    }

    return Done(iRet);
}

int CCmdInheritDrug::PreCheck (CPlayerBaseInfo & stPlayerBaseInfo, CPlayerDetailInfo& stPlayerDetailInfo, CPlayerOnlineData & stPlayerOnlineData)
{
    unsigned short usSrcRoleId = (unsigned short)(stReq.src_role_id() & 0x7FFF);
    unsigned short usDstRoleId = (unsigned short)(stReq.dst_role_id() & 0x7FFF);
    if ((usDstRoleId == usSrcRoleId)
        || (0 == usDstRoleId) || (0 == usSrcRoleId))
    {
        return ERROR_DRUG_ROLE_ID_INVALID;
    }

    //检查系统是否开启
    if (!pstMainCtrl->m_stCommConfigLoader.IsOpen(SYS_OPEN_COND_ID_14, stPlayerBaseInfo, stPlayerOnlineData))
    {
        return AnsClients(ERROR_SYS_NOT_OPEN);
    }

    //金币传承, 检查VIP等级
    int iOpt = stReq.opt();
    int iRet;
    _bUsingGold = (OPT_INHERIT_GOLD == iOpt ? true : false);
    if (_bUsingGold)
    {
        int iMaxResetCount = 0;
        iRet = pstMainCtrl->m_stVipMgr.GetVipDestNum(stPlayerBaseInfo._chVipLevel, VIP_MODULE_ID_16, iMaxResetCount);
        CHECK_RETURN(iRet);

        if (iMaxResetCount <= 0)
        {
            return ERROR_DRUG_GOLD_INHERIT;
        }
    }

    iRet = pstMainCtrl->m_stDrugMgr.CheckRoleId(stPlayerDetailInfo, usSrcRoleId);
    CHECK_RETURN(iRet);

    iRet = pstMainCtrl->m_stDrugMgr.CheckRoleId(stPlayerDetailInfo, usDstRoleId);
    CHECK_RETURN(iRet);

    CDrugData & stSrcDrug = pstMainCtrl->m_stDrugMgr.GetUserDrug(stPlayerDetailInfo, usSrcRoleId);
    CDrugData & stDstDrug = pstMainCtrl->m_stDrugMgr.GetUserDrug(stPlayerDetailInfo, usDstRoleId);

    iRet = pstMainCtrl->m_stDrugMgr.GetInheritCost(stSrcDrug, stDstDrug, _iNeedSilver, _iNeedGold);
    CHECK_RETURN(iRet);

    if (OPT_INHERIT_GOLD == iOpt
        && stPlayerBaseInfo._iGold < _iNeedGold)
    {
        return ERROR_GOLD_LESS;
    }

    if (OPT_INHERIT_SILVER == iOpt
        && stPlayerBaseInfo._i64Silver < _iNeedSilver)
    {
        return ERROR_SILVER_LESS;
    }

    return 0;
}
